﻿using Microsoft.EntityFrameworkCore;
using mozhi.smarterp.Finance.EntityFrameworkCore;
using mozhi.smarterp.Finance.Finances.Repository;
using mozhi.smarterp.Finance.Querys;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using System.Linq;

namespace mozhi.smarterp.Finance.Finances
{
    public class JournalRepository : EfCoreRepository<FinanceDbContext, Journal , Guid>, IJournalRepository
    {
        public JournalRepository(IDbContextProvider<FinanceDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }

        public async Task<List<Journal>> FindAsync(JournalPageQuery query)
        {
            //var dbQuery = query.IncludeDetail ? DbContext.Set<Journal>().Include(x => x.Items).AsNoTracking() : DbContext.Set<Journal>().AsNoTracking();

            //if (query.AccountIds != null && query.AccountIds.Count > 0)
            //    query.Ids = DbContext.Set<JournalItem>().AsNoTracking().Where(x => query.AccountIds.Contains(x.AccountId)).Select(x => x.JournalId).ToList();

            //var journals = await dbQuery.
            //    WhereIf(query.Id.HasValue, x => x.Id == query.Id).
            //    WhereIf(query.StartDate.HasValue, x => x.Date >= query.StartDate.Value).
            //    WhereIf(query.EndDate.HasValue, x => x.Date <= query.EndDate.Value).
            //    WhereIf(query.StartPeriod.HasValue, x => x.Period >= query.StartPeriod.Value).
            //    WhereIf(query.EndPeriod.HasValue, x => x.Period <= query.EndPeriod.Value).
            //    WhereIf(!query.Keyword.IsNullOrEmpty(), x => x.Keyword != null && x.Keyword.Contains(query.Keyword)).
            //    WhereIf(query.Approved.HasValue, x => x.Approved == query.Approved.Value).
            //    WhereIf(query.Period.HasValue, x => x.Period == query.Period.Value).
            //    WhereIf(query.SourceType != default, x => x.SourceType == query.SourceType).
            //    WhereIf(query.NumberPrefixId.HasValue, x => x.NumberPrefixId == query.NumberPrefixId)
            //    .Skip((query.PageIndex - 1) * query.PageSize).Take(query.PageSize)
            //    .ToListAsync();

            //return journals;
            throw new NotImplementedException();
        }

        public async Task<Journal> FindAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default)
        {
            var dbQuery = includeDetails ? DbContext.Set<Journal>().Include(x => x.Items).AsNoTracking() : DbContext.Set<Journal>().AsNoTracking();

            return await dbQuery.FirstOrDefaultAsync(x => x.Id == id);
        }

        public async Task<List<int>> FindNumbersAsync(Guid numberPrefixId , int period)
        {
            var numbers = await DbContext.Set<Journal>().AsNoTracking().Where(x => x.NumberPrefixId == numberPrefixId && x.Period == period)
                .Select(x => int.Parse(x.Number)).ToListAsync();

            return numbers;
        }

        public async Task<List<KeyValuePair<Guid, List<string>>>> FindNumberKeyvaluesAsync(int period)
        {
            var numbers = from a in DbContext.Set<Journal>()
                          where a.Period == period

                          group a by a.NumberPrefixId into g
                          select new KeyValuePair<Guid, List<string>>(g.Key, g.Select(x => x.Number).ToList());

            return await numbers.ToListAsync();
        }

        public Task<Journal> GetAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default)
        {
            var journal = DbContext.Set<Journal>().Include(x => x.Items).FirstOrDefaultAsync(x => x.Id == id);

            return journal;
        }

        public async Task<int> GetCountAsync(JournalPageQuery query)
        {
            //var dbQuery = DbContext.Set<Journal>().AsNoTracking();

            //if (query.AccountIds != null && query.AccountIds.Count > 0)
            //    query.Ids = DbContext.Set<JournalItem>().AsNoTracking().Where(x => query.AccountIds.Contains(x.AccountId)).Select(x => x.JournalId).ToList();

            //var count = await dbQuery.
            //    WhereIf(query.Id.HasValue, x => x.Id == query.Id).
            //    WhereIf(query.Ids != null && query.Ids.Count > 0, x => query.Ids.Contains(x.Id)).
            //    WhereIf(query.StartDate.HasValue, x => x.Date >= query.StartDate.Value).
            //    WhereIf(query.EndDate.HasValue, x => x.Date <= query.EndDate.Value).
            //    WhereIf(query.StartPeriod.HasValue, x => x.Period >= query.StartPeriod.Value).
            //    WhereIf(query.EndPeriod.HasValue, x => x.Period <= query.EndPeriod.Value).
            //    WhereIf(!query.Keyword.IsNullOrEmpty(), x => x.Keyword != null && x.Keyword.Contains(query.Keyword)).
            //    WhereIf(query.Approved.HasValue, x => x.Approved == query.Approved.Value).
            //    WhereIf(query.Period.HasValue, x => x.Period == query.Period.Value).
            //    WhereIf(query.ExclusionId.HasValue, x => x.Id != query.ExclusionId.Value).
            //    WhereIf(query.SourceType != default, x => x.SourceType == query.SourceType).
            //    WhereIf(query.NumberPrefixId.HasValue, x => x.NumberPrefixId == query.NumberPrefixId).
            //    WhereIf(!query.Number.IsNullOrEmpty(), x => x.Number == query.Number)
            //    .CountAsync();

            //return count;
            throw new NotImplementedException();
        }

        public async Task<List<Journal>> UpdateAsync(List<Journal> journals)
        {
            foreach (var journal in journals)
            {
                await UpdateAsync(journal);
            }

            return journals;
        }
    }
}
